package com.zhugy.comparecode;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import com.alibaba.fastjson.JSON;
import com.zhugy.comparecode.config.CompareBinaryConfig;
import com.zhugy.comparecode.util.CommonUtils;

public class CompareBinaryFile {
	
	private static int BUFFER_SIZE = 8192;

	public static void main(String[] args) {
		if (args == null || args.length == 0) {
			throw new RuntimeException("参数为空");
		}
		String configJson = args[0];
		CompareBinaryConfig config = JSON.parseObject(configJson, CompareBinaryConfig.class);
		if (CommonUtils.isEmpty(config.getPath1())) {
			throw new RuntimeException("path1不能为空");
		}
		
		if (CommonUtils.isEmpty(config.getPath2())) {
			throw new RuntimeException("path2不能为空");
		}
		
		File f1 = new File(config.getPath1());
		if (!f1.exists()) {
			throw new RuntimeException("path1对应的文件不存在");
		}
		if (f1.isDirectory()) {
			throw new RuntimeException("path1对应的是文件夹不是二进制文件");
		}
		
		File f2 = new File(config.getPath2());
		if (!f2.exists()) {
			throw new RuntimeException("path2对应的文件不存在");
		}
		if (f2.isDirectory()) {
			throw new RuntimeException("path2对应的是文件夹不是二进制文件");
		}
		
		compare(f1, f2, config);
	}

	private static void compare(File f1, File f2, CompareBinaryConfig config) {
		byte[] bs1 = new byte[BUFFER_SIZE];
		byte[] bs2 = new byte[BUFFER_SIZE];
		BufferedInputStream in1, in2;
		try {
			in1 = new BufferedInputStream(new FileInputStream(f1));
		} catch (FileNotFoundException e) {
			throw new RuntimeException("f1文件不存在", e);
		}
		try {
			in2 = new BufferedInputStream(new FileInputStream(f2));
		} catch (FileNotFoundException e) {
			try {
				in1.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			throw new RuntimeException("f2文件不存在", e);
		}
		
		int offset = 0;
		try {
			aa:while (true) {
				int len1 = in1.read(bs1);
				int len2 = in2.read(bs2);
				if (len1 <= 0) {
					if (len2 > 0) {
						System.out.println("偏移" + toHex(offset) + "不一致，" + "左边完结，右边还有");
						break aa;
					} else {
						System.out.println("比较完结");
						break aa;
					}
				}
				for (int i = 0; i < len1; i++) {
					if (i >= len2) {
						System.out.println("偏移" + toHex(offset) + "不一致，" + "右边完结，左边还有");
						break aa;
					}
					byte b1 = bs1[i];
					byte b2 = bs2[i];
					if (b1 != b2) {
						System.out.println("偏移" + toHex(offset) + "不一致，" + toHex(b1) + "VS" + toHex(b2));
						if (!config.isContinueOnDiff()) {
							continue;
						}
					}
					offset++;
				}
				if (len1 < len2) {
					System.out.println("偏移" + toHex(offset) + "不一致，" + "左边完结，右边还有");
					break aa;
				}
			}
		} catch(Exception e) {
			
		} finally {
			try {
				in1.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				in2.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}

	/**
	 * 假设是无符号整数，如果是有符号的，此方法可能不对
	 * 
	 * @param offset
	 * @return
	 */
	private static String toHex(int offset) {
		if (offset == 0) {
			return "0x0";
		}
		StringBuilder sb = new StringBuilder();
		int temp = offset;
		while (temp > 0) {
			int digital = temp & 0xf;
			if (digital <= 9) {
				sb.append((char) (digital + '0'));
			} else {
				sb.append((char) (digital - 10 + 'A'));
			}
			temp >>= 4;
		}
		return "0x" + sb.reverse().toString();
	}
	
	private static String toHex(byte offset) {
		StringBuilder sb = new StringBuilder();
		int digital = offset & 0xf;
		if (digital <= 9) {
			sb.append((char) (digital + '0'));
		} else {
			sb.append((char) (digital - 10 + 'A'));
		}
		
		digital = (offset >> 4) & 0xf;
		if (digital <= 9) {
			sb.append((char) (digital + '0'));
		} else {
			sb.append((char) (digital - 10 + 'A'));
		}
		
		return sb.reverse().toString() + "H";
	}
}
